/*
 *  Copyright 2011 yura.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.vcforms.transform_t2d;

import java.util.Map;
import java.util.Properties;
import org.opu.doc2db.document.datadocument.Document;
import org.opu.doc2db.document.datadocument.Paragraph;
import org.opu.doc2db.document.datadocument.ParagraphList;
import org.opu.doc2db.document.datadocument.TextBlock;
import org.opu.doc2db.document.datadocument.TextParagraph;
import org.opu.vcforms.datasource.DataReceiver;
import org.opu.vcforms.datasource.Storage;
import org.opu.vcforms.template.bean.Content;
import org.opu.vcforms.template.bean.SmartTable;
import org.opu.vcforms.template.bean.Var;
import org.opu.vcforms.transform_t2d.content.ContentProcessor;
import org.opu.vcforms.transform_t2d.table.TableProcessor;
import org.opu.vcforms.transform_t2d.var.VarProcessor;

/**
 *  Transform input template to output document
 * @author yura
 */
public class Transformer extends MainProcessor implements Processor<Document, Document>{

    /**
     *  Create new instance
     * @param receiver needed to send query and get request from database
     * @param userSettings can be empty (user data).
     * @param systemSettings systemSettings system settings (course, semestr, ...).
     *  If it null loads system properties - {@link System#getProperties()}.
     * @param contentProcessor content (can be null)
     */
    public Transformer(DataReceiver receiver, Map<String, Storage> userSettings,
            Properties systemSettings, ContentProcessor contentProcessor) {
        super(receiver, userSettings, systemSettings, contentProcessor);
    }

    /**
     *  Create new instance with nullable content (for main node - document).
     * @param receiver needed to send query and get request from database
     * @param userSettings can be empty (user data).
     * @param systemSettings systemSettings system settings (course, semestr, ...).
     *  If it null loads system properties - {@link System#getProperties()}.
     */
    public Transformer(DataReceiver receiver, Map<String, Storage> userSettings,
            Properties systemSettings) {
        super(receiver, userSettings, systemSettings);
    }


    /**
     *  Transform input template to output document
     * @param in input template
     * @return output document
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    @Override
    public Document transform(Document in) throws IllegalArgumentException,
            UnsupportedOperationException {
        Document out = new Document();

        Logger.out("Start process " + in);
        Logger.var(Logger.SPACE, "  ");

        this.transformer(out, in);

        Logger.rm(Logger.SPACE);
        Logger.out("End process " + in + " to " + out);

        return out;
    }

    /**
     *  Process each in paraghraph of in-list and added it to out list.
     * @param out output paragraph list
     * @param in input paragraph list
     * @return output paragraph list
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public ParagraphList transformer(ParagraphList out, ParagraphList<Paragraph> in) 
            throws IllegalArgumentException, UnsupportedOperationException {

        for (Paragraph paragraph : in) {
            this.add(out, paragraph);
        }

        return out;
    }

    /**
     *  Processes data and added it to source
     * @param source
     * @param data
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    private void add(ParagraphList source, Paragraph data)
            throws IllegalArgumentException, UnsupportedOperationException {

        if (data instanceof Content){
            Content content = (Content) data;
            
            ContentProcessor contProc = new ContentProcessor(contentProcessor,
                    null, content);
            Transformer t = new Transformer(dbManager, userSettings, 
                    systemSettings, contProc);
            
            contProc.setTransformer(t);
            try {
                contProc.init();
            } catch (NullPointerException ex) {
                String msg = "Can init content processor";
                throw  new IllegalArgumentException(msg, ex);
            }

            do { //until has steps
                t.transformer(source, content);
            } while (contProc.hasData());
        }

        else if (data instanceof SmartTable){
            TableProcessor tp = new TableProcessor(this);
            source.elementsAdd(tp.transform((SmartTable) data));
        }

        else if (data instanceof TextParagraph){
            source.elementsAdd(processeParagraph((TextParagraph) data));
        }

        else {//rest elements have no difference with document elements.
            source.elementsAdd(data);
        }
    }

    private TextParagraph processeParagraph(TextParagraph paragraph)
            throws UnsupportedOperationException, IllegalArgumentException {
        
        VarProcessor vp = new VarProcessor(contentProcessor, systemSettings, configuration);
        return processeParagraph(paragraph, vp);
    }

    /**
     *  Parse each text block that is var, in text paragraph
     * @param tp text paragraph with text blocks and vars inside
     * @param vp processor, that create text block from var.
     * @return text paragraph with text blocks instead of var.
     */
    public TextParagraph processeParagraph(TextParagraph tp, VarProcessor vp)
            throws UnsupportedOperationException, IllegalArgumentException {
        
        TextParagraph ret = new TextParagraph(tp.getId());
        for (TextBlock tb : tp) {

            if (tb instanceof Var){
                ret.elementsAdd(vp.transform((Var) tb));
            } else {
                ret.elementsAdd(tb);
            }
        }
        return ret;
    }
}
